package org.xc.uvc_camera;

import android.text.TextUtils;

import com.github.hiteshsondhi88.libffmpeg.FFmpeg;
import com.github.hiteshsondhi88.libffmpeg.FFmpegExecuteResponseHandler;

import org.xc.uvc_camera.encoder.AacEncoder;
import org.xc.uvc_camera.encoder.H264Encoder;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;

import me.zuichu.mp4coder.Container;
import me.zuichu.mp4coder.muxer.FileDataSourceImpl;
import me.zuichu.mp4coder.muxer.Movie;
import me.zuichu.mp4coder.muxer.builder.DefaultMp4Builder;
import me.zuichu.mp4coder.muxer.tracks.AACTrackImpl;
import me.zuichu.mp4coder.muxer.tracks.h264.H264TrackImpl;

class CollectUtil {

    private CollectUtil() {}
    private static CollectUtil instance;
    synchronized static CollectUtil getInstance() {
        if (instance == null) {
           instance = new CollectUtil();
        }
        return instance;
    }

    private boolean h264Over = false;
    private boolean aacOver = false;

    void start(String fileName, int width, int height) {

        H264Encoder.getInstance().start(fileName, width, height, new H264Encoder.IOnEncoderCallback() {
            @Override
            public void over(String fileName) {
                h264Over = true;
                muxe(fileName);
            }
        });

        AacEncoder.getInstance().startRecording(fileName, new AacEncoder.IOnEncoderCallback() {
            @Override
            public void over(String fileName) {
                aacOver = true;
                muxe(fileName);
            }
        });
    }

    void writeVideoData(byte[] yuv420sp) {
        H264Encoder.getInstance().write(yuv420sp);
    }

    void close() {
        H264Encoder.getInstance().close();
        AacEncoder.getInstance().close();
    }

    private void muxe(String fileName) {
        if (h264Over && aacOver) {
            h264Over = false;
            aacOver = false;

            try {
                File aacFile = FileUtil.getFile(fileName + ".aac");
                File h264File = FileUtil.getFile(fileName + ".h264");
                String mp4 = FileUtil.createFile(fileName + ".mp4");

                String cmd = "-i " + aacFile.getAbsolutePath() + " -i " + h264File.getAbsolutePath() + " " + mp4;
                FFmpeg.getInstance(MyApplication.INSTANCE).execute(cmd.split(" "), new FFmpegExecuteResponseHandler() {
                    @Override
                    public void onSuccess(String message) {
                        aacFile.delete();
                        h264File.delete();
                    }

                    @Override
                    public void onProgress(String message) {

                    }

                    @Override
                    public void onFailure(String message) {
                        writeError(message,fileName);
                    }

                    @Override
                    public void onStart() {
                    }

                    @Override
                    public void onFinish() {
                    }
                });
            } catch (Exception e) {
                writeError(e.getMessage(),fileName);
            }
        }
    }

    private void writeError(String error,String fileName) {
        if (TextUtils.isEmpty(error) || TextUtils.isEmpty(fileName)) {
            return;
        }
        try {
            FileOutputStream fos = new FileOutputStream(FileUtil.createFile(fileName + ".txt"));
            fos.write(error.getBytes());
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    class MuserRunnable implements Runnable {
        private String fileName;

        public MuserRunnable(String fileName) {
            this.fileName = fileName;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            File h264File = FileUtil.getFile(fileName + ".h264");
            File aacFile = FileUtil.getFile(fileName + ".aac");
            if (h264File == null || aacFile == null) {
                return;
            }

            try {
                H264TrackImpl h264Track = new H264TrackImpl(new FileDataSourceImpl(h264File));
                AACTrackImpl aacTrack = new AACTrackImpl(new FileDataSourceImpl(aacFile));

                Movie movie = new Movie();
                movie.addTrack(h264Track);
                movie.addTrack(aacTrack);

                FileChannel fileChannel = new FileOutputStream(FileUtil.createFile(fileName + ".mp4")).getChannel();

                Container container = new DefaultMp4Builder().build(movie);
                container.writeContainer(fileChannel);
                fileChannel.close();

                h264File.delete();
                aacFile.delete();
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    FileOutputStream fos = new FileOutputStream(FileUtil.createFile(fileName + ".txt"));
                    fos.write(e.getMessage().getBytes());
                    fos.flush();
                    fos.close();
                } catch (FileNotFoundException e1) {
                    e.printStackTrace();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
}
